package com.kws.merchant.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.documents4j.job.LocalConverter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfWriter;
import com.kws.common.core.domain.R;
import com.kws.common.core.utils.StringUtils;
import com.kws.common.security.auth.AuthUtil;
import com.kws.common.security.utils.SecurityUtils;
import com.kws.merchant.domain.*;
import com.kws.merchant.domain.po.*;
import com.kws.merchant.domain.vo.*;
import com.kws.merchant.mapper.MerchantScoreMapper;
import com.kws.merchant.mapper.UserPartnerMapper;
import com.kws.merchant.service.*;
import com.kws.merchant.util.FileUtil;
import com.kws.system.api.RemoteToolService;
import com.kws.system.api.domain.PhotovoltaicDto;
import com.kws.system.api.domain.PhotovoltaicVo;
import com.kws.system.api.domain.SysUser;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDTrueTypeFont;
import org.apache.pdfbox.pdmodel.font.PDType1Font;
import org.apache.poi.xwpf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import com.documents4j.api.*;
import com.documents4j.api.*;
import com.itextpdf.text.Document;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URL;
import java.util.concurrent.Future;

import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : zhangbenting
 * @date : 2024/11/8 15:10
 * @Version: 1.0
 */
@Service
public class UserPartnerServiceImpl implements UserPartnerService {

    @Resource
    private UserPartnerMapper userPartnerMapper;

    @Autowired
    private MerchantService merchantService;

    @Autowired
    private ServeService serveService;

    @Autowired
    private ServeImgService serveImgService;

    @Autowired
    private AttentionService attentionService;

    @Autowired
    private DeviceRemarkService deviceRemarkService;

    @Autowired
    private MerchantScoreMapper merchantScoreMapper;

    @Autowired
    private ItemUserSchemeService itemUserSchemeService;

    @Autowired
    private ItemSchemeMerchantService itemSchemeMerchantService;

    @Autowired
    private OnlineInquiryService onlineInquiryService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private GoodsViewService goodsViewService;

    @Autowired
    private RemoteToolService remoteToolService;

    @Autowired
    private CalculationResultsService calculationResultsService;

    @Value("${minio.ENDPOINT}")
    private String minioUrl;

    @Override
    public List<UserServeVo> getRecommendServe() {
        List<UserServeVo> recommendServe = userPartnerMapper.getRecommendServe();
        recommendServe.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getImg())) {
                item.setImg(FileUtil.fixFileName() + item.getImg());
            }
        });
        return recommendServe;
    }

    @Override
    public List<UserServeVo> getPopularServe() {
        List<UserServeVo> popularServe = userPartnerMapper.getPopularServe();
        popularServe.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getImg())) {
                item.setImg(FileUtil.fixFileName() + item.getImg());
            }
        });
        return userPartnerMapper.getPopularServe();
    }

    @Override
    public List<MerchantDetailVo> getVideoNumber() {
        List<MerchantDetailVo> videoNumber = userPartnerMapper.getVideoNumber();
        videoNumber.forEach(item -> {
            if (StringUtils.isNotEmpty(item.getShopImg())) {
                item.setShopImg(FileUtil.fixFileName() + item.getShopImg());
            }
        });
        return videoNumber;
    }

    @Override
    public Page<UserServeVo> getServeList(UserServePo userServePo) {
        // 计算分页参数
        int offset = (userServePo.getPageSize() - 1) * userServePo.getTotalPage();
        int pageSize = userServePo.getTotalPage();

        // 获取总记录数
        Long count = userPartnerMapper.userServeCount(userServePo.getServeName(),
                userServePo.getType(),
                userServePo.getMerchantName(),
                userServePo.getShopsId(),
                userServePo.getMerchantType());
        // 构建分页对象
        Page<UserServeVo> page = new Page<>(offset, pageSize, count);
        if (count <= 0) {
            return page;
        }

        // 查询服务列表
        List<UserServeVo> userServeVoList = userPartnerMapper.userServeList(
                userServePo.getServeName(),
                userServePo.getMerchantName(),
                userServePo.getType(),
                userServePo.getShopsId(),
                userServePo.getMerchantType(),
                offset,
                pageSize);

        if (CollectionUtils.isEmpty(userServeVoList)) {
            return page;
        }

        // 提取服务ID列表
        List<Long> serveIdList = userServeVoList.stream()
                .map(UserServeVo::getServeId)
                .collect(Collectors.toList());

        // 查询设备备注信息
        List<DeviceRemark> remarkServeList = deviceRemarkService.list(
                Wrappers.<DeviceRemark>lambdaQuery()
                        .in(DeviceRemark::getDeviceId, serveIdList)
                        .eq(DeviceRemark::getRemarkType, 1)
                        .eq(DeviceRemark::getEnable, 1));

        // 将备注按设备ID分组
        Map<Long, List<DeviceRemark>> remarkMap = remarkServeList.stream()
                .collect(Collectors.groupingBy(DeviceRemark::getDeviceId));

        // 处理服务列表
        userServeVoList.forEach(userServeVo -> {
            // 处理评论数及首条评论
            List<DeviceRemark> remarkList = remarkMap.get(userServeVo.getServeId());
            if (!CollectionUtils.isEmpty(remarkList)) {
                userServeVo.setCommentNum(remarkList.size());
                OptionalDouble average = remarkList.stream()
                        .filter(remark -> remark.getStarLevel() != null)
                        .mapToInt(DeviceRemark::getStarLevel)
                        .average();
                userServeVo.setScore(average.isPresent() ? String.format("%.1f", average.getAsDouble()) : "0.0");
                DeviceRemark firstComment = remarkList.stream()
                        .filter(remark -> remark.getPid().equals(0))
                        .max(Comparator.comparingLong(DeviceRemark::getId))
                        .orElse(null);
                if (firstComment != null) {
                    userServeVo.setFirstComment(firstComment.getRemark());
                }
            }

            // 处理图片URL
            if (StringUtils.isNotEmpty(userServeVo.getImg())) {
                userServeVo.setImg(FileUtil.fixFileName() + userServeVo.getImg());
            }

            //计算距离
            String lngLat = userServePo.getLngLat();
            if (StringUtils.isNotEmpty(lngLat)) {
                //商家经纬度
                String companyAddressLng = userServeVo.getCompanyAddressLng();
                String companyAddressLat = userServeVo.getCompanyAddressLat();
                if (StringUtils.isNotEmpty(companyAddressLng) && StringUtils.isNotEmpty(companyAddressLat)){
                    //当前经纬度
                    StringTokenizer tokens = new StringTokenizer(lngLat, ",");
                    double userLng = Double.parseDouble(tokens.nextToken());
                    double userLat = Double.parseDouble(tokens.nextToken());
                    double companyLng = Double.parseDouble(companyAddressLng);
                    double companyLat = Double.parseDouble(companyAddressLat);
                    //计算距离
                    Double distance = calculateDistance(userLat, userLng, companyLat, companyLng);
                    //设置距离
                    userServeVo.setDistance(distance.toString());
                }
            }
        });

        page.setRecords(userServeVoList);
        return page;
    }

    /**
     * 使用 Haversine 公式计算两点之间的距离。
     *
     * @param lat1 第一点的纬度
     * @param lon1 第一点的经度
     * @param lat2 第二点的纬度
     * @param lon2 第二点的经度
     * @return 两点之间的距离，单位：千米
     */
    public Double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
        final double RADIUS_OF_EARTH = 6371;
        double latDistance = Math.toRadians(lat2 - lat1);
        double lonDistance = Math.toRadians(lon2 - lon1);
        double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
                + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
                * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
        double v = RADIUS_OF_EARTH * c;
        BigDecimal bd = new BigDecimal(Double.toString(v));
        bd = bd.setScale(3, RoundingMode.HALF_UP); // 保留三位小数，四舍五入
        double roundedV = bd.doubleValue();
        return roundedV;
    }

    @Override
    public ServeInfoVo getServeInfo(UserServePo userServePo) {
        SysUser sysUser = AuthUtil.getLoginUser().getSysUser();
        Long userId = sysUser.getUserId();
        ServeInfoVo serveInfoVo = userPartnerMapper.userServe(userServePo.getServeId());
        LambdaQueryWrapper<AttentionEntity> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(AttentionEntity::getAttentionTypeId, serveInfoVo.getServeId());
        wrapper.eq(AttentionEntity::getType, 1);
        wrapper.eq(AttentionEntity::getUserId, userId);
        serveInfoVo.setIsCollect(ObjectUtils.isNotNull(attentionService.list(wrapper)));

        if (StringUtils.isNotEmpty(serveInfoVo.getImg())) {
            serveInfoVo.setImg(FileUtil.fixFileName() + serveInfoVo.getImg());
        }
        if (StringUtils.isNotEmpty(serveInfoVo.getShopsLog())) {
            serveInfoVo.setShopsLog(FileUtil.fixFileName() + serveInfoVo.getShopsLog());
        }
        List<String> imgList = new ArrayList<>();
        List<ServeImg> serveImgs = serveImgService.listByServeId(userServePo.getServeId());
        if (serveImgs != null && serveImgs.size() > 0) {
            for (ServeImg serveImg : serveImgs) {
                if (StringUtils.isNotEmpty(serveImg.getImg())) {
                    String img = FileUtil.fixFileName() + serveImg.getImg();
                    imgList.add(img);
                }
            }
        }
        serveInfoVo.setImgArr(imgList);

        // 查询设备备注信息
        List<DeviceRemark> remarkServeList = deviceRemarkService.list(
                Wrappers.<DeviceRemark>lambdaQuery()
                        .eq(DeviceRemark::getDeviceId, userServePo.getServeId())
                        .eq(DeviceRemark::getRemarkType, 1)
                        .eq(DeviceRemark::getEnable, 1));
        // 处理评论数及首条评论
        if (!CollectionUtils.isEmpty(remarkServeList)) {
            serveInfoVo.setCommentNum(remarkServeList.size());
            OptionalDouble average = remarkServeList.stream()
                    .filter(remark -> remark.getStarLevel() != null)
                    .mapToInt(DeviceRemark::getStarLevel)
                    .average();
            serveInfoVo.setScore(average.isPresent() ? String.format("%.1f", average.getAsDouble()) : "0.0");
        }

        //计算距离
        //当前经纬度
        String lngLat = userServePo.getLngLat();
        if (StringUtils.isNotEmpty(lngLat)) {
            //商家经纬度
            String companyAddressLng = serveInfoVo.getCompanyAddressLng();
            String companyAddressLat = serveInfoVo.getCompanyAddressLat();
            if (StringUtils.isNotEmpty(companyAddressLng) && StringUtils.isNotEmpty(companyAddressLat)){
                StringTokenizer tokens = new StringTokenizer(lngLat, ",");
                double userLng = Double.parseDouble(tokens.nextToken());
                double userLat = Double.parseDouble(tokens.nextToken());
                double companyLng = Double.parseDouble(companyAddressLng);
                double companyLat = Double.parseDouble(companyAddressLat);
                //计算距离
                Double distance = calculateDistance(userLat, userLng, companyLat, companyLng);
                //设置距离
                serveInfoVo.setDistance(distance.toString());
            }
        }
        //商品浏览记录
        Long addGoodsViewId = goodsViewService.addGoodsView(serveInfoVo.getShopsId(), serveInfoVo.getServeId(), 1);
        serveInfoVo.setGoodsViewId(addGoodsViewId);
        return serveInfoVo;
    }

    //todo
    @Override
    public List<DesignVo> getDesignOrConstructionUnitList(String type) {
        LambdaQueryWrapper<Merchant> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Merchant::getUserRole, type);
        List<Merchant> merchantList = merchantService.list(wrapper);
        List<DesignVo> designVos = new ArrayList<>();
        if (ObjectUtils.isNotEmpty(merchantList)) {
            List<Long> merchantIds = merchantList.stream().map(Merchant::getId).collect(Collectors.toList());
            List<AttentionEntity> list = attentionService.list(Wrappers.<AttentionEntity>lambdaQuery()
                    .eq(AttentionEntity::getUserId, SecurityUtils.getUserId())
                    .in(AttentionEntity::getAttentionTypeId, merchantIds)
                    .eq(AttentionEntity::getType, 1));
            Map<Long, List<AttentionEntity>> attentionMap =
                    list.stream().collect(Collectors.groupingBy(AttentionEntity::getAttentionTypeId));
            for (Merchant merchant : merchantList) {
                DesignVo designVo = new DesignVo();
                //获取商家评分和评论数
                GoodsRemarkVo goodsRemarkVo = deviceRemarkService.scoreAvg(merchant.getId());
                designVo.setScore(goodsRemarkVo.getScore().toString());
                designVo.setCommentNum(goodsRemarkVo.getAllRemark().toString());
                //获取用户是否收藏设计商
                List<AttentionEntity> attentionEntities = attentionMap.get(merchant.getId());
                if (ObjectUtils.isNull(attentionEntities)) {
                    designVo.setIsCollect("0");
                } else {
                    designVo.setIsCollect("1");
                }
                //获取商家距离用户距离

                designVos.add(designVo);
            }
        }
        return designVos;
    }

    @Override
    public ShopsScoreVo getShopsScore(Long merchantId) {
        ShopsScoreVo shopsScore = merchantScoreMapper.getShopsScore(merchantId);
        if (ObjectUtils.isNotNull(shopsScore)) {
            if (StringUtils.isNotEmpty(shopsScore.getShopImg())) {
                shopsScore.setShopImg(FileUtil.fixFileName() + shopsScore.getShopImg());
            }
            return shopsScore;
        }
        return new ShopsScoreVo();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean buyService(BuyServicePo buyServicePo) {
        SysUser sysUser = AuthUtil.getLoginUser().getSysUser();
        Long userId = sysUser.getUserId();
        String phonenumber = sysUser.getPhonenumber();
        String userName = sysUser.getUserName();
        UserServeVo serveInfo = merchantScoreMapper.getServeInfo(buyServicePo.getServeId());
        OnlineInquiryEntity schemeParam = buyServicePo.getSchemeParam();
        onlineInquiryService.save(schemeParam);
        //todo 生成方案、上传方案到minio
        //保存方案
        ItemUserSchemeEntity itemUserSchemeEntity = new ItemUserSchemeEntity();
        itemUserSchemeEntity.setUserId(userId);
        itemUserSchemeEntity.setSchemeId(schemeParam.getId());
        itemUserSchemeEntity.setSchemeName("方案名称");
        itemUserSchemeEntity.setSchemeFile("方案文件");
        itemUserSchemeService.save(itemUserSchemeEntity);
        //保存到商家报价表
        ItemSchemeMerchant itemSchemeMerchantEntity = new ItemSchemeMerchant();
        itemSchemeMerchantEntity.setMerchantId(serveInfo.getShopsId());
        itemSchemeMerchantEntity.setSchemeId(schemeParam.getId());
        itemSchemeMerchantEntity.setStatus(1);
        itemSchemeMerchantEntity.setUserId(userId);
        itemSchemeMerchantEntity.setServeId(buyServicePo.getServeId());
        itemSchemeMerchantService.save(itemSchemeMerchantEntity);
        //生成订单 todo 增加失效时间
        Order order = new Order();
        order.setOrderNo(String.valueOf(IdWorker.getId()));
        order.setUserId(userId);
        order.setGoodsId(buyServicePo.getServeId());
        order.setGoodsName(serveInfo.getName());
        order.setGoodsImg(serveInfo.getImg());
        order.setMerchantId(serveInfo.getShopsId());
        order.setMerchantName(serveInfo.getShopsName());
        order.setSchemeId(schemeParam.getId());
        order.setType(1);
        order.setEnable("1");
        order.setStatus(0);
        order.setIsEvaluate(0);
        order.setGoodsCount(1);
        order.setConsignee(userName);
        order.setConsigneePhone(phonenumber);

        return orderService.save(order);
    }

    @Override
    public Page<QuotationVo> offerManage(OrderInfoPo orderInfoPo) {
        orderInfoPo.setPageSize((orderInfoPo.getPageSize() - 1) * orderInfoPo.getTotalPage());
        SysUser sysUser = AuthUtil.getLoginUser().getSysUser();
        Long userId = sysUser.getUserId();
        Long count = userPartnerMapper.getOfferManageCount(userId);
        Page<QuotationVo> page = new Page<>(orderInfoPo.getPageSize(), orderInfoPo.getTotalPage());
        if (count > 0) {
            List<QuotationVo> offerManage = userPartnerMapper.getOfferManage(userId,
                    orderInfoPo.getPageSize(), orderInfoPo.getTotalPage());
            page.setRecords(offerManage);
            return page;
        }
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ItemUserSchemeEntity createProgramme(CreateProgrammePo createProgrammePo) {
        SysUser sysUser = AuthUtil.getLoginUser().getSysUser();
        Long userId = sysUser.getUserId();
        // 创建一个映射，用于存储要替换的占位符和它们对应的值
        Map<String, String> placeholders = getMappingInfo(createProgrammePo);
        Map<String, String> investTypeParam = getInvestTypeParam(createProgrammePo);
        //获取模板
        String programmeUrl = getProgramme(createProgrammePo.getProgrammeType());
        // 打开现有的 Word 模板文件
        try (InputStream templateStream = getClass().getClassLoader().getResourceAsStream(programmeUrl);
             XWPFDocument document = new XWPFDocument(templateStream)) {

            // 替换占位符
            replacePlaceholdersInDocument(document, placeholders);
            //转成pdf文件
            MultipartFile multipartFile = convertXwpfDocumentToPdf(document);
//            // 将更新后的 Word 文档保存为字节数组
//            ByteArrayOutputStream wordOut = new ByteArrayOutputStream();
//            document.write(wordOut);
//            byte[] wordBytes = wordOut.toByteArray();
//            // 转换为 MultipartFile
//            MultipartFile multipartFile = new ByteArrayMultipartFile(wordBytes,
//                    "programme_" + IdWorker.getId() + ".docx");
            // 上传到 MinIO
            String url = merchantService.uploadCompanyFile(multipartFile);
            String schemeUrl = FileUtil.subFileName(url);
            //将方案存库
            ItemUserSchemeEntity itemUserSchemeEntity = new ItemUserSchemeEntity();
            itemUserSchemeEntity.setUserId(userId);
            itemUserSchemeEntity.setSchemeFile(schemeUrl);
            itemUserSchemeEntity.setSchemeName(createProgrammePo.getProgrammeType() + "_" + IdWorker.getId());
            itemUserSchemeService.save(itemUserSchemeEntity);
            //参数存库
            CalculationResultsEntity calculationResultsEntity = new CalculationResultsEntity();
            calculationResultsEntity.setUserId(userId);
            calculationResultsEntity.setCalculationType(createProgrammePo.getProgrammeType());
            calculationResultsEntity.setCalculationParam(createProgrammePo.getProgrammeParam());
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = objectMapper.writeValueAsString(placeholders);
            calculationResultsEntity.setCalculationResults(jsonString);
            calculationResultsEntity.setSchemeId(itemUserSchemeEntity.getSchemeId());
            calculationResultsService.save(calculationResultsEntity);
            return itemUserSchemeEntity;
        } catch (Exception e) {
            // 使用日志记录更详细的信息
            throw new RuntimeException("生成方案失败", e);
        }
    }

    // 转换 XWPFDocument 为 MultipartFile 类型的 PDF 文件
    public MultipartFile convertXwpfDocumentToPdf(XWPFDocument document ) throws Exception {
        // 使用 iText 创建 PDF 文件
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        Document pdfDocument = new Document();
        PdfWriter.getInstance(pdfDocument, byteArrayOutputStream);
        pdfDocument.open();

        // 设置支持中文的字体（你需要提供中文字体的路径）
        URL resource = getClass().getClassLoader().getResource("stic/simhei.ttf");
        BaseFont baseFont = BaseFont.createFont(resource.getPath(), BaseFont.IDENTITY_H, BaseFont.EMBEDDED); // SimSun 字体路径
        Font font = new Font(baseFont, 12, Font.NORMAL);  // 创建字体对象

        // 处理段落，将 Word 文档的内容写入 PDF
        List<XWPFParagraph> paragraphs = document.getParagraphs();
        for (XWPFParagraph paragraph : paragraphs) {
            StringBuilder text = new StringBuilder();
            for (XWPFRun run : paragraph.getRuns()) {
                text.append(run.text());  // 获取每个段落中的文本
            }
            // 使用设置的中文字体
            pdfDocument.add(new Paragraph(text.toString(), font));  // 添加到 PDF 文档
        }

        pdfDocument.close();

        // 获取 PDF 字节数据
        byte[] pdfBytes = byteArrayOutputStream.toByteArray();

        // 创建一个 MultipartFile 对象，将 PDF 文件封装成 MultipartFile 类型
        return new MockMultipartFile("document.pdf", "document.pdf", "application/pdf", pdfBytes);
    }

    public String getProgramme(String programmeType) {
        switch (programmeType) {
            case "光伏":
                return "stic/光伏测算测试模板.docx";
            case "储能":
                break;
            case "充电桩":
                break;
            case "风电":
                break;
            case "光储一体化":
                break;
            case "光储充一体化":
                break;
        }
        return null;
    }

    public Map<String, String> getInvestTypeParam(CreateProgrammePo createProgrammePo) {
        Map<String, String> investTypeParamMap = new HashMap<>();
        String investTypeParam = createProgrammePo.getInvestTypeParam();
        InvestTypePo investTypePo = JSON.parseObject(investTypeParam, InvestTypePo.class);
        investTypeParamMap.put("investType", investTypePo.getInvestType());
        investTypeParamMap.put("incomePresets", investTypePo.getIncomePresets());
        investTypeParamMap.put("loanDuration", investTypePo.getLoanDuration());
        investTypeParamMap.put("incomeYear", investTypePo.getIncomeYear());
        investTypeParamMap.put("repaymentDuration", investTypePo.getRepaymentDuration());
        investTypeParamMap.put("repaymentWay", investTypePo.getRepaymentWay());
        investTypeParamMap.put("loanInterestRate", investTypePo.getLoanInterestRate());
        investTypeParamMap.put("investRecycleDuration", investTypePo.getInvestRecycleDuration());
        return investTypeParamMap;
    }

    public Map<String, String> getMappingInfo(CreateProgrammePo createProgrammePo) {
        Map<String, String> placeholders = new HashMap<>();
        switch (createProgrammePo.getProgrammeType()) {
            case "光伏":
                String programmeParam = createProgrammePo.getProgrammeParam();
                PhotovoltaicDto photovoltaicDto = JSON.parseObject(programmeParam, PhotovoltaicDto.class);
                R<PhotovoltaicVo> photovoltaicVoR = remoteToolService.photovoltaicCalculation(photovoltaicDto);
                PhotovoltaicVo photovoltaicVo = photovoltaicVoR.getData();
                placeholders.put("ztz", photovoltaicVo.getZtz());
                placeholders.put("dzgm", photovoltaicVo.getDzgm());
                placeholders.put("nfdl", photovoltaicVo.getNfdl());
                placeholders.put("zfdl", photovoltaicVo.getZfdl());
                placeholders.put("nsy", photovoltaicVo.getNsy());
                placeholders.put("zsy", photovoltaicVo.getZsy());
                placeholders.put("nywcb", photovoltaicVo.getNywcb());
                placeholders.put("mkwgfjscb", photovoltaicVo.getMkwgfjscb());
                placeholders.put("hbzq", photovoltaicVo.getHbzq());
                placeholders.put("tzsyl", photovoltaicVo.getTzsyl());
                placeholders.put("zjtl", photovoltaicVo.getZjtl());
                return placeholders;
            case "储能":
                break;
            case "充电桩":
                break;
            case "风电":
                break;
            case "光储一体化":
                break;
            case "光储充一体化":
                break;
        }
        return null;
    }

    // 替换占位符方法
    private void replacePlaceholdersInDocument(XWPFDocument document, Map<String, String> placeholders) {
        // 替换段落中的占位符
        for (XWPFParagraph paragraph : document.getParagraphs()) {
            mergeRunsAndReplace(paragraph, placeholders);
        }

        // 替换表格中的占位符
        for (XWPFTable table : document.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    for (XWPFParagraph paragraph : cell.getParagraphs()) {
                        mergeRunsAndReplace(paragraph, placeholders);
                    }
                }
            }
        }
    }

    // 合并 XWPFRun 并替换占位符
    private void mergeRunsAndReplace(XWPFParagraph paragraph, Map<String, String> placeholders) {
        StringBuilder paragraphText = new StringBuilder();
        List<XWPFRun> runs = paragraph.getRuns();

        if (runs != null) {
            for (XWPFRun run : runs) {
                paragraphText.append(run.text());
            }

            String replacedText = paragraphText.toString();
            for (Map.Entry<String, String> entry : placeholders.entrySet()) {
                replacedText = replacedText.replace("${" + entry.getKey() + "}", entry.getValue());
            }

            // 清空原有段落的内容并重新设置
            for (int i = runs.size() - 1; i >= 0; i--) {
                paragraph.removeRun(i);
            }
            XWPFRun newRun = paragraph.createRun();
            newRun.setText(replacedText, 0);
        }
    }
}
